

#include <stdlib.h>
#include <stdio.h>

#include "fractal.h"

#define MAPSHIFT       8
#define MAPSIZE        (1<<MAPSHIFT)
#define BYTE(a)        (a&(MAPSIZE-1))
#define CLOUD_SIZE     100 // 1=small clouds. 100 is a good value.
#define INDEX(x,y)     ((BYTE(y)<<MAPSHIFT)+BYTE(x))
#define RANDOM(range)  (rand() % (range))

byte *fractalmap=NULL;
byte *colormap=NULL;

void
SmoothMap(byte *buf)		/* smooth 256x256x8bits texture */
{
  int x,y,a;
  
  for (x = 0; x < 256; x++)
    for (y = 0; y < 256; y++)
      {
	buf[INDEX(x,y)]=( buf[INDEX(x-1,y-1)]
			 +buf[INDEX(x-1,y+1)]
			 +buf[INDEX(x+1,y-1)]
			 +buf[INDEX(x+1,y+1)]
			 +buf[INDEX(x  ,y-1)]
			 +buf[INDEX(x  ,y+1)]
			 +buf[INDEX(x-1,y)]
			 +buf[INDEX(x  ,y)]
			 +buf[INDEX(x+1,y)])/9;	
      }
}

int
RandPixel(int x,int y,int x1,int y1,int x2,int y2)
{
  int col;
  
  col = (rand()%200 - 100) * (abs(x-x1)+abs(y-y1)) / CLOUD_SIZE +
    ((fractalmap[INDEX(x1,y1)]+fractalmap[INDEX(x2,y2)]) >> 1);

  if (col < 0) col = 0;
  if (col > 255) col = 254;

  fractalmap[INDEX(x,y)]=(char)col;
  
  return col;
}


int
RandPixel2(int c,int s)
{
  int col;
  
  col = (rand()%200 - 100) * (2*s)/(CLOUD_SIZE) +c;

  if (col < 0) col = 0;
  if (col >= 255) col = 254;

  return col;
}

void
fractal(int x,int y,int size)
{
  int s,p;
  int xs,ys,x2,y2;
  int size2=(size>>1);
  
  if(size<2)
    return;
  
  xs=x+size2;
  ys=y+size2;
  x2=x+size;
  y2=y+size;
  
  if ((p =fractalmap[INDEX(xs, y)]) == 255)
    p = RandPixel(xs,y,x,y,x2,y);

  if ((p = fractalmap[INDEX(x,ys)]) == 255)
    p = RandPixel(x,ys,x,y,x,y2);

  if ((p = fractalmap[INDEX(x2,ys)]) == 255)
    p = RandPixel(x2,ys,x2,y,x2,y2);

  if ((p = fractalmap[INDEX(xs,y2)]) == 255)
    p = RandPixel(xs,y2,x,y2,x2,y2);

  s=fractalmap[INDEX(x,y)]+fractalmap[INDEX(x2,y2)]+fractalmap[INDEX(x,y2)]+fractalmap[INDEX(x2,y)];
  fractalmap[INDEX(xs,ys)]=RandPixel2((s>>2),size);

  fractal(x,y,size2);
  fractal(xs,y,size2);
  fractal(x,ys,size2);
  fractal(xs,ys,size2);
}


void
MakeColorMap()
{
  int x,y,temp;
  
  for (x = 0; x < 256; x++)
    for (y = 0; y < 256; y++)
      {
	temp = fractalmap[INDEX(x+1,y)]-fractalmap[INDEX(x,y)];
	temp=((temp*330)>>5)+128;
	//temp=((temp*450)>>6)+128;
	colormap[INDEX(x,y)] = temp;
      }
}

void
CreateMap()
{
  int i;
  
  srand((unsigned)time(NULL));
  fractalmap=(byte *)malloc(65536*sizeof(char));
  colormap=(byte *)malloc(65536*sizeof(char));
  memset(fractalmap,255,MAPSIZE*MAPSIZE);  

  fractalmap[0]=(rand()%127+64);

  printf("Calculating %dx%d fractal..",MAPSIZE,MAPSIZE);
  fractal(0,0,256);
  printf("\nSmoothing map..");
  SmoothMap(fractalmap);
  printf("\nCreating color map..");
  MakeColorMap();
  printf("\nSmoothing color map..");
  SmoothMap(colormap);
  printf("\n");
  fflush(stdout);
}

void
KillMap()
{
  if(fractalmap!=NULL)
    {
      free(fractalmap);
      fractalmap=NULL;
    }
  if(colormap!=NULL)
    {
      free(colormap);
      colormap=NULL;
    }
}
